//结构体的序列化与反序列化
use serde::{Deserialize, Serialize};
#[derive(Serialize, Deserialize, Debug)]
struct Point {
    x: i32,
    y: i32,
}
//第一种枚举的序列化与反序列化,为了JSON格式好看，加入serde(tag)宏
#[derive(Debug, Serialize, Deserialize)]
#[serde(tag = "WeekDay")]
enum Week {
    Monday,
    Tuesday,
    Wednesday,
    Thursday,
    Friday,
    Saturday,
    Sunday,
}
//第二种枚举的序列化与反序列化,显示标签与内容,如serde(tag, content)
#[derive(Debug, Serialize, Deserialize)]
#[serde(tag = "type", content = "ip")]
enum IP {
    IPv4(String),
    IPv6(String)
}
//Unit Struct的序列化与反序列化
#[derive(Debug, Serialize, Deserialize)]
struct UnitStruct;

//约定或重命名序列化与反序列化
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
//将大小写约定驼峰或#[serde(rename="studentId")]
struct Student {
    pub name: String,
    //#[serde(rename="studentId")]
    pub student_id: String,
}

//在序列化与反序列化过程中忽略某个字段
/*
*#[serde(skip)]同时忽略这个字段
*/
#[derive(Debug, Serialize, Deserialize)]
struct User {
    name: String,
    age: u8,
    tel: u64,
    #[serde(skip, default="default_addr")]
    ///给addr设置一个默认,忽略addr这个字段#[serde(skip)]
    addr: String,
}
fn default_addr()-> String {
    "天津".to_owned()
}

//Skip If 作用于Option字段和空的vector字段
#[derive(Debug, Clone, Serialize, Deserialize)]
struct Teacher {
    name: String,
    #[serde(skip_serializing_if="Option::is_none")]
    former_name: Option<String>,
    teacher_id: String,
    #[serde(skip_serializing_if = "Vec::is_empty")]
    pets: Vec<String>,
}
//Flatten嵌套struct展平
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
struct Worker {
    name: String,
    worker_id: String,
    #[serde(skip_serializing_if = "Option::is_none", flatten)]
    //展平实现#[serde(skip_serializing_if = "Option::is_none", flatten)]
    side_info: Option<SideInfo>
}
#[derive(Debug, Clone, Serialize, Deserialize, Default)]
#[serde(rename_all = "camelCase")]
struct SideInfo {
    #[serde(skip_serializing_if = "Option::is_none")]
    pets: Option<Vec<String>>,
    #[serde(skip_serializing_if = "Option::is_none")]
    address: Option<String>,
}
//枚举上的标签
#[derive(Debug, Clone, Serialize, Deserialize)]
enum TeacherList {
    #[serde(rename="Teacher")]
    Teacher1(Teacher),
    #[serde(rename="Teacher")]
    Teacher2(Teacher)
}
//枚举上不加标签
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(untagged)]
enum TeacherL {
    Teacher1(Teacher),
    Teacher2(Teacher)
}
//枚举上内部标签
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(tag= "type", rename_all="camelCase")]
enum TeacherType {
    Regular(Teacher),
    Leader(Teacher),
    SubLeader(Teacher),
}
//枚举上相邻标签
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(tag= "type", content = "teacher", rename_all="camelCase")]
enum TeacherT {
    Regular(Teacher),
    Leader(Teacher),
    SubLeader(Teacher),
}

fn main() {
    //结构体的序列化与反序列化
    let point = Point {x: 1, y: 2};
    let json: String = serde_json::to_string(&point).unwrap();
    println!("结构体序列化:{}", json);
    let point: Point = serde_json::from_str(&json).unwrap();
    println!("结构体反序列化:{:#?}", point);

    //枚举的序列化与反序列化
    let json: String = serde_json::to_string(&Week::Friday).unwrap();
    println!("枚举的序列化:{}", json);
    let week: Week = serde_json::from_str(&json).unwrap();
    println!("枚举的反序列化:{:#?}", week);
    
    //枚举的序列化与反序列化
    let json: String = serde_json::to_string(&IP::IPv4("127.0.0.1".to_string())).unwrap();
    println!("IP类型枚举序列化: {}",json);
    let ip: IP = serde_json::from_str(&json).unwrap();
    println!("IP类型枚举反序列化: {:#?}", ip);

    //unit struct的序列化与反序列化
    let json: String = serde_json::to_string(&UnitStruct).unwrap();
    println!("UnitStruct的序列化: {}", json);
    let us: UnitStruct = serde_json::from_str(&json).unwrap();
    println!("UnitStruct的反序列化: {:#?}", us);

    //约定的序列化与反序列化
    let stu = Student {name: "tom".to_owned(), student_id: "J202401".to_owned()};
    let json: String = serde_json::to_string(&stu).unwrap();
    println!("约定序列化:{}",json);
    let s: Student = serde_json::from_str(&json).unwrap();
    println!("约定反序列化: {:#?}", s);

    //忽略字段的序列化与反序列化
    let user = User {
        name: "autumner".to_owned(),
        age: 18,
        tel: 13612345678,
        addr: "天津卫国道".to_owned()
    };
    let json: String = serde_json::to_string(&user).unwrap();
    println!("忽略字段的序列化: {}", json);
    let u: User = serde_json::from_str(&json).unwrap();
    println!("忽略字段的反序列化: {:#?}", u);

    //skip if 的序列化
    let teacher = Teacher {
        name: "Mr zhang".to_owned(), 
        teacher_id: "T202401".to_owned(),
        former_name: Some("Lele".to_owned()),
        pets: vec!["TaiDi".to_owned()],
    };
    let json: String = serde_json::to_string(&teacher).unwrap();
    println!("skip if 序列化有曾用名与宠物: {}", json);
    let tea: Teacher = serde_json::from_str(&json).unwrap();
    println!("skip if 反序列化曾用名与宠物: {:#?}", tea);
    let t = Teacher {
        name: "Mr zhang".to_owned(), 
        teacher_id: "T202401".to_owned(),
        pets: vec![],
        former_name: None,
    };
    let json: String = serde_json::to_string(&t).unwrap();
    println!("skip if 序列化无曾用名与宠物: {}", json);
    
    //faltten展平实现
    let worker = Worker {
        name: "dan".to_owned(),
        worker_id: "1".to_owned(),
        side_info: Some(SideInfo{
            address: Some("天津卫国道".to_owned()),
            ..Default::default()
        })
    };
    let json: String = serde_json::to_string(&worker).unwrap();
    println!("Flatten展平结构体的序列化: {}", json);

    //枚举上的标签
    let tea1 = Teacher{name: "tom".to_owned(), teacher_id: "T202401".to_owned(), pets: vec![], former_name: Some("Jack".to_owned())};
    let tea2 = Teacher{name: "Mery".to_owned(), teacher_id: "T202499".to_owned(), pets: vec![], former_name: Some("Men".to_owned())};
    let tea_list = vec![TeacherList::Teacher1(tea1.clone()), TeacherList::Teacher2(tea2.clone())];
    println!("enum list: {:#?}", tea_list);
    //枚举上所有标签具有相同名称
    let json: String = serde_json::to_string(&tea_list).unwrap();
    println!("所有标签有相同名称: {:#}", json);
    //枚举上不加标签
    let tea_l = vec![TeacherL::Teacher1(tea1), TeacherL::Teacher2(tea2)];
    println!("枚举原始:{:#?}", tea_l);
    let json: String = serde_json::to_string(&tea_l).unwrap();
    println!("枚举上不加标签: {}", json);

    //枚举上内部标签
    let t1 = Teacher{name: "tom".to_owned(), teacher_id: "T202401".to_owned(), pets: vec![], former_name: Some("Jack".to_owned())};
    let t2 = Teacher{name: "Mery".to_owned(), teacher_id: "T202499".to_owned(), pets: vec![], former_name: Some("Men".to_owned())};
    let t3 = Teacher{name: "Lim".to_owned(), teacher_id: "T202466".to_owned(), pets: vec![], former_name: Some("Hery".to_owned())};
    let t_list = vec![TeacherType::Regular(t1.clone()), TeacherType::Leader(t2.clone()), TeacherType::SubLeader(t3.clone())];
    println!("枚举原始: {:#?}", t_list);
    let json: String = serde_json::to_string(&t_list).unwrap();
    println!("枚举的内部标签: {}", json);

    //枚举上相符标签
    let t_l = vec![TeacherT::Regular(t1), TeacherT::Leader(t2), TeacherT::SubLeader(t3)];
    let json: String = serde_json::to_string(&t_l).unwrap();
    println!("枚举的相邻标签: {}", json);

}
